#pragma once
#include<iostream>
#include<string>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<functional>
#include"Log.hpp"
#include"InetAddr.hpp"
using namespace LogModule;

using func_t=std::function<std::string(const std::string&,InetAddr&)>;
const int defaultfd=-1;

class UdpServe
{
public:
    UdpServe(uint16_t port,func_t func)
    :_socket(defaultfd)
    ,_port(port)
    //,_ip(ip)
    ,_isrunning(false)
    ,_func(func)
    {};

    void Init()
    {
        _socket=socket(AF_INET,SOCK_DGRAM,0);
        if(_socket<0)
        {
            LOG(LogLevel::FATAL)<<"创建套接字失败";
            exit(1);
        }
        LOG(LogLevel::INFO)<<"创建套接字成功";

        struct sockaddr_in local;
        bzero(&local,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(_port);
        local.sin_addr.s_addr=INADDR_ANY;

        int n=bind(_socket,(struct sockaddr*)&local,sizeof(local));
        if(n<0)
        {
            LOG(LogLevel::FATAL)<<"bind error";
            exit(2);
        }
        LOG(LogLevel::INFO)<<"bind success";
         
    };
    void Start()
    {
        _isrunning=true;
        while(_isrunning)
        {
            char buffer[1024];
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            ssize_t s = recvfrom(_socket,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
            if(s>0)
            {
                InetAddr client(peer);
                buffer[s]=0;
                LOG(LogLevel::DEBUG)<<"buffer:"<<buffer;
                //sendinfo
                std::string resault=_func(buffer,client);
               
                sendto(_socket,resault.c_str(),resault.size(),0,(struct sockaddr*)&peer,len);
                
            } 
        }

    };
    ~UdpServe()
    {};
private:
    int _socket;
    uint16_t _port;
    //std::string _ip;
    bool _isrunning;
    func_t _func;
};